package com.tansun.easycare.rule.ml.algorithm.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.http.conn.HttpHostConnectException;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tansun.easycare.core.config.Global;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.ml.algorithm.entity.AlogrithmVariables;
import com.tansun.easycare.rule.ml.algorithm.entity.ApplyData;
import com.tansun.easycare.rule.ml.algorithm.entity.DataVariableList;
import com.tansun.easycare.rule.ml.algorithm.entity.DatabaseConn;
import com.tansun.easycare.rule.ml.algorithm.entity.FormulaDict;
import com.tansun.easycare.rule.ml.algorithm.entity.ImgVariables;
import com.tansun.easycare.rule.ml.algorithm.entity.MuntiTables;
import com.tansun.easycare.rule.ml.algorithm.entity.PyRequest;
import com.tansun.easycare.rule.ml.algorithm.entity.PyResponse;
import com.tansun.easycare.rule.ml.algorithm.entity.StockVariables;
import com.tansun.easycare.rule.ml.algorithm.entity.TicketVariables;
import com.tansun.easycare.rule.ml.algorithm.service.IAlgorthmService;
import com.tansun.easycare.rule.ml.model.entity.MlDataModel;
import com.tansun.easycare.rule.utils.PyHttpUtil;


/**
 * 机器学习算法服务实现ServiceImpl
 * @author xch
 * @version 2018-08-23
 */

@Service("iAlgrthmService")
public class AlgrthmServiceImpl implements IAlgorthmService{
	
	public static String DOWNLOAD_URL = Global.getConfig("ssdpyurl")+"/downloadFile";
	public static String BASE_URL = Global.getConfig("ssdpyurl")+ "/modelServer";
	public static String UPLOAD_URL = Global.getConfig("ssdpyurl")+ "/upload";
	
	/**
	 * 加载模型
	 * @param model
	 * @return PyResponse
	 */
	@Override
	public PyResponse loadModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"load");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 在服务中创建模型
	 * @return
	 */
	@Override
	public PyResponse createModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"create");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 删除模型
	 * @return
	 */
	@Override
	public PyResponse delModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"delete");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 删除模型
	 * @return
	 */
	@Override
	public PyResponse delModel(List<MlDataModel> mlDataModelList) {
		PyRequest req = new PyRequest(mlDataModelList,"deleteList");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 删除模型训练部分
	 * @return
	 */
	@Override
	public PyResponse modelTrainDel(MlDataModel mlDataModel){
		PyRequest req = new PyRequest(mlDataModel,"modelTrainDel");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 保存模型
	 * @return
	 */
	@Override
	public PyResponse saveModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"save");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 模型转换成可以发布的形式
	 * @param mlDataModel
	 * @return
	 */
	public PyResponse transSaveType(MlDataModel mlDataModel){
		PyRequest req = new PyRequest(mlDataModel,"transSaveType");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 模型更新
	 * @return
	 */
	@Override
	public PyResponse updateModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"update");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 数据导入
	 * @return
	 */
	@Override
	public PyResponse dataLoad(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"dataLoad");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 获取数据
	 * @return
	 */
	@Override
	public PyResponse getDataStatistics(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getDataStatistics");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 获取算法流程
	 * @return
	 */
	@Override
	public PyResponse getWorkflows(MlDataModel mlDataModel,String currentSite) {
		PyRequest req = new PyRequest(mlDataModel,currentSite,"getWorkflows");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 更新算法流程
	 * @return
	 */
	@Override
	public PyResponse updateWorkflows(MlDataModel mlDataModel,String currentSite) {
		PyRequest req = new PyRequest(mlDataModel,currentSite,"updateWorkflows");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 进行模型训练
	 * @return
	 */
	@Override
	public PyResponse trainModel(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"trainModel");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 获取训练结果
	 * @return
	 */
	@Override
	public PyResponse getTrainData(MlDataModel mlDataModel){
		PyRequest req = new PyRequest(mlDataModel,"getTrainData");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 
	 * @return
	 */
	@Override
	public PyResponse getTransferData(MlDataModel mlDataModel){
		PyRequest req = new PyRequest(mlDataModel,"getTransferData");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 测试模型
	 * @return
	 */
	@Override
	public PyResponse testAnalysis(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"testAnalysis");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 应用模型
	 * @return
	 */
	@Override
	public PyResponse modelApply(MlDataModel mlDataModel,ApplyData applyData,ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,applyData,imgVariables,"modelApply");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 下载文件，图片等
	 * @return
	 */
	@Override
	public byte[] downloadFile(String savepath) {
		byte[] resBytes = null;
		try {
			resBytes = PyHttpUtil.doPostDownload(DOWNLOAD_URL,savepath);
		} catch (IOException e) {
			// TODO Auto-generated method stub
			e.printStackTrace();
		}
		return resBytes;
	}
	
	/**
	 * 发送Post请求
	 * @param operate
	 * @return
	 */
	@Override
    public PyResponse doPostRequest(PyRequest req){
		String reqjson = JSONObject.toJSONString(req);
		PyResponse response = null;
		try {
			
			String respStr = PyHttpUtil.doPost(BASE_URL,reqjson);
			response = JSON.parseObject(respStr, PyResponse.class);
			if ("fail".equals(response.getResultCode())){
				String errorCode = response.getResponse().get("error").toString();
				throw new BizException(errorCode);
			}
		} catch(HttpHostConnectException e){
			throw new BizException("E-300001");
		} catch (IOException e) {
			// TODO Auto-generated method stub
			e.printStackTrace();
		}
		return response;
    }

	@Override
	public PyResponse parameterSetup(MlDataModel mlDataModel, AlogrithmVariables alogrithmVariables) {
		PyRequest req = new PyRequest(mlDataModel,alogrithmVariables,"parameterSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse dataSetup(MlDataModel mlDataModel, AlogrithmVariables alogrithmVariables) {
		PyRequest req = new PyRequest(mlDataModel,alogrithmVariables,"dataSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse dataProcess(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"dataProcess");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse visualPreview(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"visualPreview");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse getVariableMsg(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getVariableMsg");
		PyResponse response = doPostRequest(req);
		return response;
	}

	public PyResponse setUsedType(MlDataModel mlDataModel,AlogrithmVariables alogrithmVariables){
		PyRequest req = new PyRequest(mlDataModel,alogrithmVariables,"setUsedType");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 上传数据
	 */
	@Override
	public PyResponse upload(String dataFile,String modelId,String apply) {
		PyResponse response = null;
		try {
			String respStr = PyHttpUtil.uploadPost(dataFile, modelId, apply, UPLOAD_URL);
			response = JSON.parseObject(respStr, PyResponse.class);
			if ("fail".equals(response.getResultCode())){
				throw new RuntimeException("python服务请求失败，请检查参数及python服务设置");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return response;
	}
	/**
	 * 上传数据
	 */
	@Override
	public PyResponse upload(File file,Map<String,String> inputMap) {
		PyResponse response = null;
		try {
			String respStr = PyHttpUtil.uploadPost(file, inputMap, UPLOAD_URL);
			response = JSON.parseObject(respStr, PyResponse.class);
			if ("fail".equals(response.getResultCode())){
				throw new RuntimeException("python服务请求失败，请检查参数及python服务设置 \n"+response.getResponse().get("error"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return response;
	}
	/**
	 * 上传数据
	 */
	@Override
	public PyResponse upload(byte[] byteArr,String filename,Map<String,String> inputMap) {
		PyResponse response = null;
		try {
			String respStr = PyHttpUtil.uploadPost(byteArr, filename, inputMap, UPLOAD_URL);
			response = JSON.parseObject(respStr, PyResponse.class);
			if ("fail".equals(response.getResultCode())){
				throw new RuntimeException("python服务请求失败，请检查参数及python服务设置 \n"+response.getResponse().get("error"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return response;
	}

	/**
	 * 删除缺失值
	 * @param mlDataModel,dataVriables
	 * @return
	 */
	@Override
	public PyResponse deleteMissingValue(MlDataModel mlDataModel,DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"deleteMissingValue");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 替换缺失值
	 * @param mlDataModel,dataVriables
	 * @return
	 */
	@Override
	public PyResponse replaceMissingValue(MlDataModel mlDataModel,DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"replaceMissingValue");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 数据集变量设置
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse dataVariablesSetup(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"dataVariablesSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 数据集平衡设置
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse dataBanlanceSetup(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"dataBanlanceSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 数据集分割设置，分为训练集和测试集
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse dataSplitSetup(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"dataSplitSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 数据集目标变量标签化
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse dataTargetVarsLabelSetup(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"dataTargetVarsLabelSetup");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 获取图片数据
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse getImgData(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getImgData");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 获取图片数据，分析目标列
	 * @param mlDataModel
	 * @param dataVriables
	 * @return
	 */
	@Override
	public PyResponse getTargetVarAnalysis(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getTargetVarAnalysis");
		PyResponse response = doPostRequest(req);
		return response;
	}
	

	@Override
	public PyResponse getSCcurve(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getSCcurve");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	public PyResponse setVaribleOperate(MlDataModel mlDataModel,ImgVariables imgVariables){
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"setVaribleOperate");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 聚类类别重命名
	 * @param mlDataModel
	 * @param ApplyData
	 * @return
	 */
	public PyResponse className(MlDataModel mlDataModel,ApplyData applyData) {
		PyRequest req = new PyRequest(mlDataModel,applyData,null,"className");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 获取类别数据
	 * @param mlDataModel
	 * @return
	 */
	public PyResponse getClass(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getClass");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	@Override
	public PyResponse getBestKData(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getBestKData");
		PyResponse response = doPostRequest(req);
		return response;
	}
	/**
	 * 获取混合矩阵
	 * @param mlDataModel
	 * @return
	 */
	@Override
	public PyResponse getConfusionMatrix(MlDataModel mlDataModel,ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getConfusionMatrix");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 获取roc曲线矩阵
	 * @param mlDataModel
	 * @return
	 */
	@Override
	public PyResponse getRocCurve(MlDataModel mlDataModel,ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getRocCurve");
		PyResponse response = doPostRequest(req);
		return response;
	}

	/**
	 * 获取lift曲线
	 * @param mlDataModel
	 * @return
	 */
	@Override
	public PyResponse getLiftCurve(MlDataModel mlDataModel,ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"getLiftCurve");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	/**
	 * 获取对比数据
	 * @param mlDataModel
	 * @return
	 */
	public PyResponse getCompareTestData(MlDataModel mlDataModel,ImgVariables imgVariables){
		PyRequest req = new PyRequest(mlDataModel, imgVariables,"getCompareTestData");
		PyResponse response = doPostRequest(req);
		return response;
	}


	/**
	 * 获取输入参数信息
	 */
	@Override
	public PyResponse getInputArgsMsg(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getInputArgsMsg");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse getDataSetInputMsg(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getDataSetInputMsg");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	@Override
	public PyResponse getParameter(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"getParameter");
		PyResponse response = doPostRequest(req);
		return response;
	}
	
	@Override
	public PyResponse dataModify(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"dataModify");
		PyResponse response = doPostRequest(req);
		return response;
	}
	public PyResponse loadDataByDBTabel(MlDataModel mlDataModel,DatabaseConn databaseConn){
		PyRequest req = new PyRequest(mlDataModel,databaseConn,"loadDataByDBTabel");
		PyResponse response = doPostRequest(req);
		return response;
	}
	public PyResponse loadStockData(MlDataModel mlDataModel,StockVariables stockVariables){
		PyRequest req = new PyRequest(mlDataModel,stockVariables,"loadStockData");
		PyResponse response = doPostRequest(req);
		return response;
	}
	public PyResponse loadTicketData(MlDataModel mlDataModel,TicketVariables ticketVariables){
		PyRequest req = new PyRequest(mlDataModel,ticketVariables,"loadTicketData");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse deleteTable(MlDataModel mlDataModel, String tableName) {
		PyRequest req = new PyRequest(mlDataModel,"deleteTable");
		req.setTableName(tableName);
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse setTarget(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"setTarget");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse replaceColumnsValue(MlDataModel mlDataModel, ImgVariables imgVariables) {
		PyRequest req = new PyRequest(mlDataModel,imgVariables,"replaceColumnsValue");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse getCorrelogramData(MlDataModel mlDataModel, MuntiTables muntiTables) {
		PyRequest req = new PyRequest(mlDataModel,muntiTables,"getCorrelogramData");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse addColumn(MlDataModel mlDataModel, FormulaDict formulaDict) {
		PyRequest req = new PyRequest(mlDataModel,formulaDict,"addColumn");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse saveFeatureData(MlDataModel mlDataModel) {
		PyRequest req = new PyRequest(mlDataModel,"saveFeatureData");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse setInOutVariable(MlDataModel mlDataModel, MuntiTables muntiTables) {
		PyRequest req = new PyRequest(mlDataModel,muntiTables,"setInOutVariable");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse dataBanlance(MlDataModel mlDataModel, MuntiTables muntiTables) {
		PyRequest req = new PyRequest(mlDataModel,muntiTables,"dataBanlance");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse getFeatureProject() {
		PyRequest req = new PyRequest("getFeatureProject");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse dataSetProcess(MlDataModel mlDataModel, String dataSetFile) {
		PyRequest req = new PyRequest(mlDataModel,"dataSetProcess");
		req.setDataSetFile(dataSetFile);
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse deleteAllNa(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"deleteAllNa");
		PyResponse response = doPostRequest(req);
		return response;
	}

	@Override
	public PyResponse replaceAllNa(MlDataModel mlDataModel, DataVariableList dataVriables) {
		PyRequest req = new PyRequest(mlDataModel,dataVriables,"replaceAllNa");
		PyResponse response = doPostRequest(req);
		return response;
	}
}
